package com.fingard.dsp.bank.directbank.srb01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7516HisTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.RetAtsTrans;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.util.PdfGenerateUtil;
import com.fingard.util.SmbFileUtil;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;

public class SRB01ReceiptPro extends SRB01Base implements IReceiptPro {
    @Override
    public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        try {
            String qryDay8 = Format.Date8Format.format(pOneDay);
            //下载回单文件
            List<String> fileLists = downPDFFile(pConfig, pReqReceipt, pOneDay);
            ReceiptDataHelper receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);//回单数据保存类，分区分表
            String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8;
            for (String file : fileLists) {
                String dateFile = localpath + File.separator + file;
                if (!new File(dateFile).exists()) {
                    WriteBankLogLn("回单数据文件下载失败：" + file);
                    return null;
                }

                //通过解析pdf内容读取字段
                String[] pdfStrArr = PdfGenerateUtil.readPDFTable(dateFile, 1000, 800).split("\r\n");
                ReceiptData rcpt = new ReceiptData();
                rcpt.ownAct = pReqReceipt.actNum;
                rcpt.ownAct = pReqReceipt.actNum;
                rcpt.bank = "20153";
                rcpt.srcSys = "SRB01";
                String TRAN_DATE = (pdfStrArr[2].substring(pdfStrArr[1].indexOf("交易日期") + 6, pdfStrArr[2].indexOf("交易时间") - 1));
                rcpt.istNbr = Format.Date8Format.format(Format.Date10Format.parse(TRAN_DATE)) +
                        (pdfStrArr[1].substring(pdfStrArr[1].indexOf("核心流水号") + 6, pdfStrArr[1].indexOf("子顺序号") - 1)) +
                        (pdfStrArr[1].split(" ")[3]);
                //回单号格式 日期+核心流水+子顺序号
                rcpt.receiptNo = rcpt.istNbr;//SERIAL_NO 流水号
                rcpt.bnkSeqNo = rcpt.receiptNo;
                rcpt.setBusDate(pOneDay);
                rcpt.localFile = StringHelper.getRelativePath(dateFile, pConfig.localSaveMainDir);
                rcpt.srcFile = file;
                rcpt.cur = "1";
                rcpt.busRef = rcpt.istNbr;
                rcpt.downState = "2";
                rcpt.busDate = Integer.parseInt(qryDay8);
                if (!qryDay8.equals(Format.Date8Format.format(Format.Date10Format.parse(TRAN_DATE)))) {
                    WriteBankLogLn(rcpt.receiptNo + "回单数据的日期" + TRAN_DATE + "与预期" + qryDay8 + "不符");
                }
                String[] actInfo = pdfStrArr[4].split("收款账号");
                String recAct = "";
                String recActName = "";
                //当发起批量代付的情况下，只会生成一份回单文件，收款人信息为空
                if (actInfo.length < 2) {
                    recAct = "";
                } else {
                    recAct = (pdfStrArr[4].split(" ")[3]);
                    recActName = (pdfStrArr[3].split(" ")[3]);
                }
                String payAct = (pdfStrArr[4].split(" ")[1]);
                if (recAct.equals(pReqReceipt.actNum)) {
                    rcpt.moneyWay = "2";    //收入
                    rcpt.oppActNum = payAct;
                    rcpt.oppActName = (pdfStrArr[3].split(" ")[1]);
                } else {
                    rcpt.moneyWay = "1";    //支出
                    rcpt.oppActNum = recAct;
                    rcpt.oppActName = recActName;
                }
                rcpt.amount = new BigDecimal(file.substring(file.lastIndexOf("_") + 1, file.lastIndexOf(".")));
                rcpt.voucherNo = "";
                int inRe = receiptHelper.insertIfNotExist(rcpt, true);
                WriteBankLogLn(rcpt.receiptNo + "写入数据库，影响行数：" + inRe);
            }
            String tempPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8;

            List<String> list = receiptHelper.getIstNbrList(pReqReceipt.actNum, pOneDay);
            WriteBankLogLn(pReqReceipt.actNum + "，" + qryDay8 + "需要进行下载的回单文件个数：" + list.size());
            if (list.size() <= 0) {
                return null;
            }
            File fileDir = new File(tempPath);
            int[] retVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, receiptHelper, fileDir, list);
            //[0]总数 [1]新增 [2]已存在
            WriteBankLogLn("目录" + fileDir + "\r\n遍历总数" + retVals[0] + "，新增" + retVals[1] + "条，已存在" + (retVals[0] - retVals[1]) + "条");
        } catch (Exception e) {
            WriteBankLogLn(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 公共方法，提取pdf文件，农行是所有账号的回单一起提供，遍历所有pdf
     * [0]总数 [1]新增 [2]已存在
     */
    protected int[] getPdfLoop(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay, ReceiptDataHelper pReceiptHelper, File pDir, List<String> dataList) {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        int[] retVals = new int[2];
        retVals[0] = 0;//总pdf个数
        retVals[1] = 0;//新增
        File[] files = pDir.listFiles();
        for (File eachFile : files) {
            try {
                if (eachFile.isDirectory()) {
                    int[] subVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, pReceiptHelper, eachFile, dataList);
                    retVals[0] = retVals[0] + subVals[0];
                    retVals[1] = retVals[1] + subVals[1];
                }
                String[] nameAndExt = StringHelper.splitFileNameAndExt(eachFile.getName());
                if ("pdf".equalsIgnoreCase(nameAndExt[1])) {
                    retVals[0] = retVals[0] + 1;
                    //交易日期_核心流水_子顺序号_查询账号_金额
                    //20200108_1018111_1_200203040000000579_0.01.pdf
                    String[] nameSp = nameAndExt[0].split("_");
                    if (nameSp.length != 5) {
                        WriteBankLogLn("回单文件:" + eachFile.getName() + "文件名格式不符合预期");
                        continue;
                    }
                    for (String istNbr : dataList) {
                        if (istNbr.equals(nameSp[0] + nameSp[1] + nameSp[2])) {
                            //重命名
                            String renameToPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8 + File.separator + pReqReceipt.actNum;
                            FileHelper.mkdirsIfNotExists(renameToPath);
                            renameToPath += File.separator + eachFile.getName();
                            File destFile = new File(renameToPath);
                            boolean reResult;
                            if (destFile.exists()) {
                                reResult = true;
                            } else {
                                reResult = eachFile.renameTo(destFile);
                            }
                            if (reResult) {
                                //数据库中存储的路径是相对pConfig.localSaveMainDir的相对路径
                                String relativePath = StringHelper.getRelativePath(destFile.getAbsolutePath(), pConfig.localSaveMainDir);
                                int inRe = pReceiptHelper.updateDownState(pReqReceipt.actNum, istNbr, relativePath, eachFile.getName(), "2");
                                if (inRe > 0) {
                                    retVals[1] = retVals[1] + 1;
                                }
                                WriteBankLogLn("回单编号" + istNbr + "，文件" + nameSp[1] + "下载成功，重命名成功，更新影响行数：" + inRe);
                            } else {
                                WriteBankLogLn("回单编号" + istNbr + "重命名失败：\r\n" + eachFile.getAbsolutePath() + "\r\n重命名为：\r\n" + renameToPath);
                            }
                            break;
                        }
                    }
                }
            } catch (Exception ex) {
                WriteBankLogLn(ex, eachFile.getAbsolutePath());
            }
        }
        return retVals;
    }

    //查询回单数据文件
    private List<String> downPDFFile(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        List<String> list = new ArrayList<String>();
        downloadStep1(pConfig, pReqReceipt, pOneDay, list);
        return list;
    }

    //下载回单第一步，通过明细接口查询核心流水号和日期
    private void downloadStep1(ReceiptProConfig pConfig, ReqQryReceipt p_reqReceipt, Date pOneDay, List<String> list) throws Exception {
        Req7516HisTrans p_req7516 = new Req7516HisTrans(p_reqReceipt.reqHeader);
        String qryDay8 = Format.Date8Format.format(pOneDay);
        RetAtsTrans retAtsTrans = new RetAtsTrans(p_req7516.reqHeader);

        try {
            WriteBankLogLn("开始查询明细......");
            XmlTextWriter xmlWriter = new XmlTextWriter();
            SRB01Header bankHeader = new SRB01Header();
            bankHeader.trCode = "200110";//交易代码
            bankHeader.reqSeqNo = p_req7516.reqHeader.transSeqID;

            writeCommonHeader(xmlWriter, bankHeader, false);
            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("acno", p_reqReceipt.actNum);
            xmlWriter.writeElementString("cur_code", convertCurToBank(p_reqReceipt.actCur));
            xmlWriter.writeElementString("start_date", qryDay8);
            xmlWriter.writeElementString("end_date", qryDay8);
            xmlWriter.writeEndElement();//body
            xmlWriter.writeEndElement();//ap
            xmlWriter.writeEndDocument();

            String[] retStrArr = sendToBank(xmlWriter.toXmlString());
            Map<String, String> serialMap = new HashMap();
            parseRespMsg(retStrArr, retAtsTrans, p_req7516.actArea, serialMap);
            //开始下载回单文件
            downloadStep2(pConfig, serialMap, p_reqReceipt, list, pOneDay);

        } catch (Exception e) {
            WriteBankLogLn("查询明细异常:" + e);
        }

    }

    //下载回单文件第二部，通过回单下载接口将回单文件下载到前置机
    private void downloadStep2(ReceiptProConfig pConfig, Map<String, String> serialMap, ReqQryReceipt p_reqReceipt, List<String> list, Date pOneDay) throws Exception {

        for (Map.Entry<String, String> entry : serialMap.entrySet()) {
            XmlTextWriter xmlWriter = new XmlTextWriter();
            SRB01Header bankHeader = new SRB01Header();
            bankHeader.trCode = "200218";//交易代码
            bankHeader.reqSeqNo = p_reqReceipt.reqHeader.transSeqID;
            writeCommonHeader(xmlWriter, bankHeader, false);
            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("serial_no", entry.getValue().split("-")[1]);
            xmlWriter.writeElementString("tr_acdt", entry.getValue().split("-")[0]);
            xmlWriter.writeElementString("req_no", entry.getValue().split("-")[2]);
            xmlWriter.writeEndElement();//body
            xmlWriter.writeEndElement();//ap
            xmlWriter.writeEndDocument();
            //region 发送请求报文，并获取响应报文
            String[] retStrArr = sendToBank(xmlWriter.toXmlString());
            //endregion

            //region 解析响应报文
            if (retStrArr[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(retStrArr[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String reportFileFlag = tmpBkReader.getFirstText("/ap/body/ReportFileFlag");
                    String fileName = tmpBkReader.getFirstText("/ap/body/ReportFileName");
                    if ("1".equals(reportFileFlag)) {
                        downFile(pConfig, p_reqReceipt, pOneDay, fileName);
                        list.add(fileName);
                    } else {
                        WriteBankLogLn("日期为：" + entry.getKey() + "流水号为" + entry.getValue() + "未查询到回单文件");
                    }
                } else {
                    WriteBankLogLn(tmpSbMsg.toString());
                }
            } else {
                WriteBankLogLn(retStrArr[1]);
            }
        }
    }

    //将前置机文件下载到本地回单目录
    private void downFile(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay, String fileName) throws Exception {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        String receiptDownType = getBankConfig().getValueAsString("receiptDownType");
        String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8;
        FileHelper.mkdirsIfNotExists(localpath);
        WriteBankLogLn("上饶银行文件下载目录：" + localpath + "，下载文件名：" + fileName);
        if ("sftp".equals(receiptDownType)) {
            //Sftp方式
            SftpPortClient sftpPortClient = null;

            try {
                FtpSet ftpSet = bankFront.getFtpSet("receipt");
                ftpSet.downDir = StringHelper.trimEnd(ftpSet.downDir, "/") + "/";
                WriteBankLogLn("SFTP下载地址" + ftpSet.serverIP + ":" + ftpSet.port);

                sftpPortClient = new SftpPortClient(ftpSet);
                WriteBankLogLn("下载到本地目录为：" + localpath);
                WriteBankLogLn("sftp目录下文件名为：" + fileName);
                FtpReceiver ftpReceiver = sftpPortClient.downloadFileByName("", localpath, fileName);
                if (ftpReceiver.isCompleted) {
                    WriteBankLogLn("下载成功，下载路径为：" + localpath + "文件名为" + fileName);
                } else {
                    WriteBankLogLn("下载失败，文件名为" + fileName);
                }
            } catch (Exception e) {
                e.printStackTrace();
                WriteBankLogLn(e);
            }
        } else if ("ftp".equals(receiptDownType)) {
            FtpSet ftpSet = bankFront.getFtpSet("receipt");
            FtpPortClient client = new FtpPortClient(ftpSet);
            FtpReceiver ftpReceiver = client.downloadFile(fileName, localpath);
            if (!ftpReceiver.isCompleted) {
                WriteBankLogLn(ftpReceiver.connMsg);
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                WriteBankLogLn("下载失败");
            } else {
                WriteBankLogLn("下载成功");
            }
        } else {
            //共享目录方式
            if (StringHelper.hasAnyChar(bankFront.bkTransFolder)) {
                if (bankFront.bkTransFolder.startsWith("smb://")) {
                    StringBuilder smbSb = new StringBuilder();
                    SmbFileUtil.smbDownload(localpath, bankFront.bkTransFolder, fileName, smbSb);
                } else {
                    String srcFilePath = StringHelper.trimEndFileSp(bankFront.bkTransFolder) + File.separator + fileName;
                    FileHelper.copyFile(srcFilePath, localpath + File.separator + fileName);
                }
            } else {
                throw new Exception("请配置银行前置机回单目录");
            }
        }
    }
}
